package org.dromara.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.dromara.admin.domain.*;
import org.dromara.admin.domain.vo.AdvanceBillVo;
import org.dromara.admin.domain.vo.OrderVo;
import org.dromara.admin.domain.vo.UserDetailVo;
import org.dromara.admin.enums.AuditStatus;
import org.dromara.admin.service.IUserDetailService;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.lessor.domain.House;
import org.dromara.system.domain.SysUser;
import org.dromara.system.service.ISysConfigService;
import org.springframework.stereotype.Service;
import org.dromara.admin.domain.bo.AccountBookBo;
import org.dromara.admin.domain.vo.AccountBookVo;
import org.dromara.admin.mapper.AccountBookMapper;
import org.dromara.admin.service.IAccountBookService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 账本Service业务层处理
 *
 * @author Lion Li
 * @date 2025-09-23
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AccountBookServiceImpl implements IAccountBookService {

    private final AccountBookMapper baseMapper;
    private final ISysConfigService sysConfigService;
    private final IUserDetailService userDetailService;

    /**
     * 查询账本
     *
     * @param id 主键
     * @return 账本
     */
    @Override
    public AccountBookVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询账本列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 账本分页列表
     */
    @Override
    public TableDataInfo<AccountBookVo> queryPageList(AccountBookBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<AccountBook> wrapper = getAccountBookInfoByJoinTable(bo);
        Page<AccountBookVo> result = baseMapper.selectJoinPage(pageQuery.build(), AccountBookVo.class, wrapper);
        return TableDataInfo.build(result);
    }

    /**
     * 联表查询AccountBook表、SysUser表
     */
    private static MPJLambdaWrapper<AccountBook> getAccountBookInfoByJoinTable(AccountBookBo bo) {
        // 使用MPJBaseMapper进行联表查询AccountBook表、SysUser表
        return new MPJLambdaWrapper<AccountBook>()
            .selectAll(AccountBook.class) // 账本表字段
            .selectAssociation(ContractBill.class, AccountBookVo::getRelatedContractBill)
            .selectAssociation("td", UserDetail.class, AccountBookVo::getTenantUserDetail)
            .selectAssociation("cu", SysUser.class, AccountBookVo::getCapitalUser)
            .selectAssociation("cd", UserDetail.class, AccountBookVo::getCapitalUserDetail)
            .leftJoin(ContractBill.class, ContractBill::getId, AccountBook::getRelatedId)
            // 租客详细信息 join
            .leftJoin(UserDetail.class, "td", on -> on.eq(UserDetail::getUserId, ContractBill::getUserId))
            // 资方代理信息 join
            .leftJoin(SysUser.class, "cu", on -> on.eq(SysUser::getUserId, AccountBook::getUserId))
            // 出租方详细信息 join
            .leftJoin(UserDetail.class, "cd", on -> on.eq(UserDetail::getUserId, AccountBook::getUserId))
            .eq(bo.getUserId() != null, AccountBook::getUserId, bo.getUserId())
            .eq(StrUtil.isNotBlank(bo.getStatus()), AccountBook::getStatus, bo.getStatus())
            .eq(StrUtil.isNotBlank(bo.getType()), AccountBook::getType, bo.getType())
            .like(StrUtil.isNotBlank(bo.getCapitalUserName()), "cu.user_name", bo.getCapitalUserName())
            .like(StrUtil.isNotBlank(bo.getRealName()), "cd.real_name", bo.getRealName())
            .like(StrUtil.isNotBlank(bo.getPhonenumber()), "cu.phonenumber", bo.getPhonenumber());
    }

    /**
     * 查询符合条件的账本列表
     *
     * @param bo 查询条件
     * @return 账本列表
     */
    @Override
    public List<AccountBookVo> queryList(AccountBookBo bo) {
        LambdaQueryWrapper<AccountBook> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AccountBook> buildQueryWrapper(AccountBookBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AccountBook> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(AccountBook::getId);
        lqw.eq(bo.getUserId() != null, AccountBook::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), AccountBook::getType, bo.getType());
        lqw.eq(bo.getAmount() != null, AccountBook::getAmount, bo.getAmount());
        lqw.eq(bo.getBalance() != null, AccountBook::getBalance, bo.getBalance());
        lqw.eq(bo.getRelatedId() != null, AccountBook::getRelatedId, bo.getRelatedId());
        lqw.eq(StringUtils.isNotBlank(bo.getRelatedTable()), AccountBook::getRelatedTable, bo.getRelatedTable());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AccountBook::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增账本
     *
     * @param bo 账本
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(AccountBookBo bo) {
        AccountBook add = MapstructUtils.convert(bo, AccountBook.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改账本
     *
     * @param bo 账本
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(AccountBookBo bo) {
        AccountBook update = MapstructUtils.convert(bo, AccountBook.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AccountBook entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除账本信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 资方申请提现
     *
     * @param bo 提现金额
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean withdrawal(AccountBookBo bo) {
        AccountBook accountBook = MapstructUtils.convert(bo, AccountBook.class);
        if (accountBook == null) {
            throw new ServiceException("提现信息不能为空");
        }
        // 判断用户账户余额是否够本次体现申请
        UserDetailVo userDetailVo = checkWithdrawalsAmount(accountBook);

        // 获取提现手续费比例
        String withdrawalRatio = sysConfigService.selectConfigByKey("sys.capital.withdrawals");
        // 申请的提现金额
        BigDecimal amount = accountBook.getAmount();
        // 提现所需手续费
        BigDecimal commission = amount.multiply(new BigDecimal(withdrawalRatio));
        // 实际到账金额
        BigDecimal actualAmount = amount.subtract(commission);

        // 插入提现申请数据
        accountBook.setAmount(amount.negate());
        accountBook.setActualAmount(actualAmount.negate());
        accountBook.setBalance(userDetailVo.getCapitalBalance().subtract(amount));
        accountBook.setRelatedId(userDetailVo.getUserId());
        accountBook.setRelatedTable("资方用户提现");
        accountBook.setStatus(AuditStatus.PENDING.getCode());
        boolean flag = baseMapper.insert(accountBook) > 0;
        if (flag) {
            bo.setId(accountBook.getId());
        }
        if (flag) {
            // 提现申请成功，更新用户账户余额
            userDetailService.updateBalance(accountBook.getUserId(), accountBook.getAmount());
        }
        return flag;
    }

    /**
     * 判断用户提现金额是否满足提现条件
     */
    private UserDetailVo checkWithdrawalsAmount(AccountBook accountBook) {
        if (accountBook.getAmount() == null) {
            throw new ServiceException("提现金额不能为空");
        }
        if (accountBook.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("请输入正确提现金额");
        }
        // 判断用户账户余额是否够本次体现申请
        UserDetailVo userDetailVo = userDetailService.queryById(accountBook.getUserId());
        if (userDetailVo.getCapitalBalance().compareTo(accountBook.getAmount()) < 0) {
            // 提现申请金额大于用户账户余额
            throw new ServiceException("提现申请金额大于用户账户余额！");
        }
        return userDetailVo;
    }

    /**
     * 后台审核资方的提现
     *
     * @param bo 提现信息
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean withdrawalReview(AccountBookBo bo) {
        AccountBook accountBook = MapstructUtils.convert(bo, AccountBook.class);
        if (BeanUtil.isEmpty(accountBook)) {
            throw new ServiceException("审核信息不能为空！");
        }
        // 1.查询申请是否存在
        AccountBook accountBookDB = baseMapper.selectById(accountBook.getId());
        if (BeanUtil.isEmpty(accountBookDB)) {
            throw new ServiceException("审核信息不存在！");
        }
        // 2.判断状态
        if (!AuditStatus.PENDING.getCode().equals(accountBookDB.getStatus())) {
            // 已审批订单，无法再次审批
            throw new ServiceException("提现审核已经处理过了！");
        }
        // 3.审核不通过
        if (AuditStatus.REJECTED.getCode().equals(bo.getStatus())) {
            // 审核不通过退回资方用户余额
            userDetailService.updateBalance(accountBookDB.getUserId(), accountBookDB.getAmount().negate());
        }
        // 4.审核通过/不通过更新状态
        accountBookDB.setStatus(bo.getStatus());
        return baseMapper.updateById(accountBook) > 0;
    }
}
